`timescale 1ns / 1ps
module ALU (
  input  [63:0] a,
  input  [63:0] b,
  input  [3:0]  alu_op,
  output reg [63:0] res
);
  reg [63:0] c;

  always @(*) begin
      case (alu_op)
          4'b0000:  begin
            c = 0;
            res = a + b;                       //ADD
          end
          4'b0001:  begin
            c = 0;
            res = a - b;                       //SUB
          end
          4'b0010: begin
            c = 0;
             res = a & b;                       //AND
          end
          4'b0011: begin
            c = 0; 
            res = a | b;                       //OR
          end
          4'b0100:  begin
            c = 0;
            res = a ^ b;                       //XOR
          end
          4'b0101:  begin
            c = 0;
            res = ($signed(a)<$signed(b))?1:0; //SLT
          end
          4'b0110:  begin
            c = 0;
            res = (a < b)?1:0;                 //SLTU
          end
          4'b0111:  begin                              //SLL
            if($signed(b)<0) c = $signed(a) << b[3:0];
            else c = a << b;
            res = c;                    
          end
          4'b1000:  begin                              //SRL
            if($signed(b)<0) c = $signed(a) >> b[3:0];
            else c = a >> b;
            res = c;
          end
          4'b1001:  begin                              //SRA
            if($signed(b)<0) c = $signed(a) >>> b[3:0];
            else c = $signed(a) >>> b;
            res = c;                    
          end
          4'b1010:  begin
            c[31:0] = a[31:0] + b[31:0];
            res = {{32{c[31]}},c[31:0]};               //ADDW
          end
          4'b1011:  begin
            c[31:0] = a[31:0] - b[31:0];                     //SUBW
            res = {{32{c[31]}},c[31:0]};
          end
          4'b1100:  begin                              //SLLW
            if($signed(b)<0) c[31:0] = $signed(a[31:0]) << b[3:0];
            else c[31:0] = a[31:0] << b[31:0];
            res = {{32{c[31]}},c[31:0]};
          end
          4'b1101: begin                               //SRLW
            if($signed(b)<0) c[31:0] = $signed(a[31:0]) >> b[3:0];
            else c[31:0] = a[31:0] >> b[31:0];
            res = {{32{c[31]}},c[31:0]};
          end
          4'b1110: begin                               //SRAW
            if($signed(b)<0) c[31:0] = $signed(a[31:0]) >>> b[3:0];
            else c[31:0] = $signed(a[31:0]) >>> b[31:0];
            res = {{32{c[31]}},c[31:0]};
          end
          4'b1111: begin                               //计算offset专用
            c = a % 8 * 8;
            res = c;
          end
      endcase
  end
endmodule